package io.jee.runshan.utils;

import io.jee.medusa.remote.RemoteConnector;
import io.jee.runshan.domain.remote.weixin.Article;
import io.jee.runshan.domain.remote.weixin.InputMessage;
import io.jee.runshan.domain.remote.weixin.OutputMessage;
import io.jee.runshan.domain.remote.weixin.WeixinResponse;

import java.io.Writer;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class WeixinConstant {
	private static final String WeixinPropertiesFile = "weixin.properties";
	private static Logger logger = LoggerFactory.getLogger(WeixinConstant.class);

	/**
	 * 最新的Token
	 */
	private static String AccessToken;
	/**
	 * 最后一次获取Token的时间（毫秒）
	 */
	private static long AccessTokenGeted = 0L;
	/**
	 * 最后一次Token的有效时间（毫秒）
	 */
	private static long AccessTokenExpiresIn = 0L;

	/**
	 * 微信公众号AppID
	 */
	private static String AppID;

	/**
	 * 微信公众号AppSecret
	 */
	private static String AppSecret;

	/**
	 * 微信公众平台接口基本路劲
	 */
	private static String ApiBaseUrl;

	/**
	 * 微信公众平台接口获取Token地址
	 */
	private static String AppTokenUrl;
	
	/**
	 * 微信访问项目的地址
	 */
	private static String rootUrl;

	private static Map<String, String> property = null;

	/**
	 * 获取最新Token
	 * 
	 * @Created: 2015年1月17日
	 * @Last_modified: 2015年1月17日 下午11:09:49
	 * @Last_modified_by: ynshun
	 * @Create_by: ynshun
	 * 
	 * @return
	 */
	public static String token() {
		try {
			long currentTime = new Date().getTime();
			if (currentTime - AccessTokenExpiresIn > AccessTokenGeted) {
				AppTokenUrl = getProperty("AppTokenUrl") + "?grant_type=client_credential&appid=" + getAppID() + "&secret=" + getAppSecret();
				logger.debug("Send WebRequest Load AccessToken...");
				WeixinResponse response = RemoteConnector.get(AppTokenUrl, null, WeixinResponse.class);
				AccessToken = response.getAccess_token();
				AccessTokenExpiresIn = response.getExpires_in() * 1000;
				AccessTokenGeted = currentTime;
				logger.debug("Load AccessToken Done...");
			}
		} catch (Exception e) {
			logger.error("网络请求获取AccessToken失败：" + e.getMessage());
		}
		System.out.println("Token:  " + AccessToken);
		return AccessToken;
	}

	public static String getApiBaseUrl() {
		if (ApiBaseUrl == null) {
			ApiBaseUrl = getProperty("ApiBaseUrl");
		}
		return ApiBaseUrl;
	}

	public static String getAppID() {
		if (AppID == null) {
			AppID = getProperty("AppID");
		}
		return AppID;
	}

	public static String getAppSecret() {
		if (AppSecret == null) {
			AppSecret = getProperty("AppSecret");
		}
		return AppSecret;
	}
	
	public static String getRootUrl() {
		if (rootUrl == null) {
			rootUrl = getProperty("rootUrl");
		}
		return rootUrl;
	}

	public static String sendUrl(String action) {
		return getApiBaseUrl() + action + "?access_token=" + token();
	}

	public static String sendUrl(String action, String paramName, Object paramValue) {
		return sendUrl(action) + "&" + paramName + "=" + paramValue;
	}

	/**
	 * 获取微信配置信息（包括国际化消息）
	 * 
	 * @Created: 2015年1月17日
	 * @Last_modified: 2015年1月17日 下午11:10:00
	 * @Last_modified_by: ynshun
	 * @Create_by: ynshun
	 * 
	 * @param key
	 * @return
	 */
	public static String getProperty(String key) {
		if (property == null) {
			property = PropertiesUtils.toMap(PropertiesUtils.loadProperties(WeixinPropertiesFile));
			logger.debug("load WeiXin Properties File Success!!!");
		}
		return property.get(key);
	}

	/**
	 * 获取微信包括国际化消息
	 * 
	 * @Created: 2015年1月17日
	 * @Last_modified: 2015年1月17日 下午11:42:57
	 * @Last_modified_by: ynshun
	 * @Create_by: ynshun
	 * 
	 * @param key
	 * @return
	 */
	public static String getProperty(Integer key) {
		return getProperty(String.valueOf(key));
	}

	public static String genMessage(OutputMessage outputMsg, InputMessage inputMsg) {
		String xml = null;
		try {
			XStream xstream = new XStream(new XppDriverImpl());
			xstream.processAnnotations(Article.class);
			xstream.alias("xml", outputMsg.getClass());
			
			setOutputMsgInfo(outputMsg, inputMsg);
			xml = xstream.toXML(outputMsg);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return xml;
	}

	// 设置详细信息
	private static void setOutputMsgInfo(OutputMessage oms, InputMessage msg) throws Exception {
		Class<?> outMsg = oms.getClass().getSuperclass();
		Field CreateTime = outMsg.getDeclaredField("CreateTime");
		Field ToUserName = outMsg.getDeclaredField("ToUserName");
		Field FromUserName = outMsg.getDeclaredField("FromUserName");
		ToUserName.setAccessible(true);
		CreateTime.setAccessible(true);
		FromUserName.setAccessible(true);
		CreateTime.set(oms, new Date().getTime());
		ToUserName.set(oms, msg.getFromUserName());
		FromUserName.set(oms, msg.getToUserName());
	}
	
	static class XppDriverImpl extends XppDriver {
		@Override
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				@Override
				protected void writeText(QuickWriter writer, String text) {
					if (!text.startsWith("<![CDATA[")) {
						text = "<![CDATA[" + text + "]]>";
					}
					writer.write(text);
				}
			};
		}
	}

}
